class Archive

  SCRATCH_DIR = File.join("public", "scratch")
  IMAGE_EXTENSIONS = %w(.jpg .jpeg .gif .png)

  def self.full_path(*path)
    File.join("comics", *path)
  end

  def self.find_all_in(path)
    p = full_path(path, '*')
    Dir[p].inject({:dirs => [], :archives => []}) do |result, f|
      result[File.directory?(f) ? :dirs : :archives] << File.basename(f)
      result
    end
  end

  def self.exists?(path)
    p = full_path(path)
    File.exists?(p) && !File.directory?(p)
  end

  def self.load(path)
    case File.extname(path)
      when '.cbz'
        Cbz.new(path)
      when '.cbr'
        Cbr.new(path)
      else
        raise 'Unknown archive type: #{path}'
    end
  end

  def initialize(path)
    @path = Archive.full_path(path)
  end

  def path
    @path
  end

  def path_dirs
    return @path_dirs if @path_dirs
    @path_dirs = []
    dir = File.dirname(path.gsub(/^\/*comics/,''))
    while !["comics",".","","/",nil].include?(dir.downcase)
      @path_dirs << dir
      dir = File.dirname(dir)
    end
    @path_dirs << ""
    @path_dirs.reverse!
  end

  def name
    File.basename(path, File.extname(path))
  end

  def filenames
    return @filenames if @filenames
    raw = get_filenames
    @filenames = raw.split("\n").select { |r| 
      r.strip!
      !r.blank? && IMAGE_EXTENSIONS.include?(File.extname(r))
    }.sort
  rescue
    nil
  end

  def short_filenames
    self.filenames.collect {|f| File.basename(f, File.extname(f))}
  end

  def file(full_path_in_archive)
    # Figure out the file location
    fn = File.join(SCRATCH_DIR, name, full_path_in_archive)
    dn = File.dirname(fn)

    # Create the directory if necessary
    FileUtils.mkdir_p(dn)

    # Extract the file
    if File.exists?(fn)
      return fn if Kapow::Config.serve_page_if_exists 
      FileUtils.rm_f(fn)
    end
    get_file(full_path_in_archive, dn)
    FileUtils.chmod_R(0666, fn, :force => true)

    # Resize the file if configured to do so.
    max_dim = Kapow::Config.page_max_dimension
    if max_dim
      begin
        require('image_science')
        ImageScience.with_image(fn) do |img|
          img.thumbnail(max_dim) do |resized| 
            resized.save(fn) 
            puts "Resized to #{resized.width}, #{resized.height}"
          end
        end
      rescue LoadError
        puts "Resizing impossible: image_science not found"
      end
    end

    fn
  rescue
    nil
  end

  def page(index)
    Page.new(self, index)
  end

  def errors
    @errors ||= []
  end


  protected
    def get_filenames
      raise 'Override to return a list of all the images in this archive.'
    end

    def get_file(full_path_in_archive)
      raise 'Override to extract specified file and return path to it.'
    end


  private
    def run(cmd)
      puts("Executing: #{cmd}")
      result = `#{cmd}`
      errors << result # FIXME: we want STDERR, not STDOUT?
      result
    end

end
